package com.daykw.ip.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Authenticator;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

public class HttpBase {

	private static Logger logger = Logger.getLogger(HttpBase.class);
	private static final java.util.Random RANDOM = new java.util.Random();

	

	public synchronized String post(String url, Map<String, String> header, Map<String, String> params)
			throws ConnectException {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "application/json, text/javascript, */*; q=0.01");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			Set<String> headers = header.keySet();
			for (String key : headers) {
				conn.setRequestProperty(key, header.get(key));
			}
			/**
			 * 参数
			 */
			StringBuffer p = new StringBuffer();
			Set<String> param = params.keySet();
			for (String k : param) {
				p.append(k + "=" + params.get(k) + "&");
			}

			if (p.length() > 0) {
				p = p.deleteCharAt(p.length() - 1);
			}

			// 发送POST请求必须设置如下两行
			conn.setConnectTimeout(30000);
			conn.setReadTimeout(30000);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(p.toString());
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			throw new java.net.ConnectException("请求错误,status code is[" + result + "]");
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * Post请求
	 * 
	 * @return
	 * @throws Exception
	 */
	public String post(String url, String charset, Map<String, String> header, Map<String, String> data)
			throws Exception {
		CustomPostMethod postMethod = new CustomPostMethod(url);
		try {
			HttpClient client = getClient(charset);
			postMethod.setRequestHeader("User-Agent",
					"Mozilla/5.0 (Windows NT " + (RANDOM.nextInt(5) + 1) + ".1) AppleWebKit/"
							+ (RANDOM.nextInt(537) + 1) + "." + (RANDOM.nextInt(11) + 1)
							+ " (KHTML, like Gecko) Chrome/" + (RANDOM.nextInt(23) + 1) + ".0."
							+ (RANDOM.nextInt(1271) + 1) + "." + (RANDOM.nextInt(95) + 1) + " Safari/"
							+ (RANDOM.nextInt(537) + 1) + "." + (RANDOM.nextInt(11) + 1) + "");
			postMethod.setRequestHeader("Accept-Encoding", "gzip,deflate,sdch");
			Set<String> headers = header.keySet();
			for (String key : headers) {
				postMethod.setRequestHeader(key, header.get(key));
			}
			Set<String> keys = data.keySet();
			NameValuePair[] ps = new NameValuePair[keys.size()];
			int index = 0;
			for (String k : keys) {
				ps[index++] = new NameValuePair(k, data.get(k));
			}
			postMethod.setRequestBody(ps);

			int statusCode = client.executeMethod(postMethod);// 回车——出拳！
			if (statusCode == 200) {
				String result = postMethod.getResponseBodyAsString();

				return result;
			}
			postMethod.abort();
			throw new java.net.ConnectException("请求错误,status code is[" + statusCode + "]");
		} catch (Exception e) {
			postMethod.abort();
			throw e;
		} finally {
			postMethod.releaseConnection();
		}

	}

	public String get(String url, String charset, Map<String, String> header) throws Exception {
		CustomGetMethod getMethod = new CustomGetMethod(url);
		String ips = null;
		try {
			HttpClient client = getClient(charset);

			/** header */
			// "User-Agent","Mozilla/5.0 /Windows; U; Windows NT 4.1; de;
			// rv:1.9.1.5) Gecko/20091102 Firefox/3.0"
			// getMethod.setRequestHeader(header);
			getMethod.setRequestHeader("User-Agent",
					"Mozilla/5.0 (Windows NT " + (RANDOM.nextInt(5) + 1) + ".1) AppleWebKit/"
							+ (RANDOM.nextInt(537) + 1) + "." + (RANDOM.nextInt(11) + 1)
							+ " (KHTML, like Gecko) Chrome/" + (RANDOM.nextInt(23) + 1) + ".0."
							+ (RANDOM.nextInt(1271) + 1) + "." + (RANDOM.nextInt(95) + 1) + " Safari/"
							+ (RANDOM.nextInt(537) + 1) + "." + (RANDOM.nextInt(11) + 1) + "");
			getMethod.setRequestHeader("Accept-Encoding", "gzip,deflate,sdch");
			if (header != null && !header.isEmpty()) {
				Set<String> keys = header.keySet();
				for (String key : keys) {
					getMethod.setRequestHeader(key, header.get(key));
				}
			}

			int statusCode = client.executeMethod(getMethod);// 回车——出拳！
			if (statusCode == 200) {
				String result = getMethod.getResponseBodyAsString();
				return result;
			} else {
				return null;
			}

		} catch (java.net.ConnectException e) {

			throw e;

		} catch (java.net.SocketTimeoutException e) {

			throw e;

		} catch (java.net.SocketException e) {

			throw e;

		} catch (org.apache.commons.httpclient.ConnectTimeoutException e) {

			throw e;

		} catch (javax.net.ssl.SSLHandshakeException e) {

			throw e;

		} catch (Exception e) {
			getMethod.abort();
			throw e;
		} finally {
			getMethod.releaseConnection();
		}

	}

	private static MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
	static {
		Integer MAX_TIME_OUT = 5000;
		// Integer MAX_IDLE_TIME_OUT = 60000;
		Integer MAX_CONN = 5000;
		connectionManager.closeIdleConnections(MAX_TIME_OUT);
		connectionManager.getParams().setParameter("http.connection-manager.max-total", MAX_CONN);
	}

	private static HttpClient getClient(String charset) {
		HttpClient client = new HttpClient(connectionManager);
		/**
		 * if(type.equals(WebsiteType.CTRIP) && Constant.isUseProxy()){ Proxy
		 * proxy = ProxyUtils.getCtripProxy(); if(proxy != null){
		 * InetSocketAddress isa = (java.net.InetSocketAddress)proxy.address();
		 * client
		 * .getHostConfiguration().setProxy(isa.getAddress().getHostAddress(),
		 * isa.getPort());
		 * logger.debug("启用代理,ip["+isa.getAddress().getHostAddress
		 * ()+":"+isa.getPort()+"]"); } }
		 */
		HttpConnectionManagerParams params = client.getHttpConnectionManager().getParams();
		params.setConnectionTimeout(5000);
		params.setSoTimeout(5000);
		params.setDefaultMaxConnectionsPerHost(500);
		params.setMaxTotalConnections(1500);
		params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

		HttpClientParams hcp = client.getParams();
		hcp.setParameter("http.connection.timeout", (long) 5 * 1000);
		hcp.setParameter("http.connection-manager.timeout", (long) 5 * 1000);
		hcp.setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charset);
		hcp.setAuthenticationPreemptive(true);
		return client;
	}

	public String getResponseBodyAsString(GetMethod getMethod) throws IOException {

		GZIPInputStream gzin;

		if (getMethod.getResponseBody() != null || getMethod.getResponseBodyAsStream() != null) {

			if (getMethod.getResponseHeader("Content-Encoding") != null

					&& getMethod.getResponseHeader("Content-Encoding").getValue().toLowerCase().indexOf("gzip") > -1) {

				// For GZip response

				InputStream is = getMethod.getResponseBodyAsStream();

				gzin = new GZIPInputStream(is);

				InputStreamReader isr = new InputStreamReader(gzin, getMethod.getResponseCharSet());

				java.io.BufferedReader br = new java.io.BufferedReader(isr);

				StringBuffer sb = new StringBuffer();

				String tempbf;

				while ((tempbf = br.readLine()) != null) {
					sb.append(tempbf);
					sb.append("\r\n");
				}
				isr.close();
				gzin.close();
				return sb.toString();
			} else {
				// For deflate response
				return getMethod.getResponseBodyAsString();
			}
		} else {
			return null;
		}

	}

	public synchronized String http(String url, Map<String, String> headers) throws Exception {
		URL u = new URL(url);
		// 创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
		URLConnection.setDefaultAllowUserInteraction(true);
		URLConnection httpsConn = u.openConnection();

		Set<String> keys = headers.keySet();
		for (String k : keys) {
			httpsConn.setRequestProperty(k, headers.get(k));
		}

		// 取得该连接的输入流，以读取响应内容
		BufferedReader insr = new BufferedReader(new InputStreamReader(httpsConn.getInputStream()));

		// 读取服务器的响应内容并显示
		StringBuffer sb = new StringBuffer();
		String s;
		while ((s = insr.readLine()) != null) {
			sb.append(s + "\n");
		}
		return sb.toString();
	}

}

class ProxyAuthenticator extends Authenticator {
	private String user, password;

	public ProxyAuthenticator(String user, String password) {
		this.user = user;
		this.password = password;
	}

	protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication(user, password.toCharArray());
	}
}
